import express, { Request, Response } from 'express';
import { authenticateJWT } from '../middleware/authMiddleware';
import { DeviceManager } from '../device/DeviceManager';
import { AppDataSource } from '../config/database';
import { BranchAccount } from '../entity/BranchAccount';
import {DeviceGroupManager} from "../device/DeviceGroupManager";
import {Device} from "../entity/Device";
import {  validateControlValue } from '../utils/validateControl';
import { getStrategy } from '../brand/strategyFactory';
import { DeviceControlCapability } from '../entity/DeviceControlCapability';

const deviceRouter = express.Router();
const dm = new DeviceManager();
const groupManager = new DeviceGroupManager();


/**
 * 获取设备列表（同步 + 查询）
 */
deviceRouter.get('/getList', authenticateJWT, async (req, res) => {
  const userId = (req as any).user.userId;

  try {
    // 查询用户的第三方授权记录
    const repo = AppDataSource.getRepository(BranchAccount);
    const bindings = await repo.find({ where: { userId } });

    for (const { brand, token } of bindings) {
      try {
        await dm.syncDevices(userId, brand, token);
      } catch (err:any) {
        console.error(`[SYNC] Failed to sync devices for ${brand}:`, err.message);
        // 继续尝试下一个品牌
      }
    }

    const allDevices = await dm.getUserDevices(userId);

    const devices = allDevices.map(d => ({
      did: d.did,
      name: d.name,
      type: d.type,
      brand: d.brand,
      group: d.gid ?? null
    }));

    res.json({
      code: 200,
      data: { devices }
    });
  } catch (err: any) {
    console.error(`[DEVICE] getList failed:`, err.message);
    res.status(500).json({
      code: 500,
      message: 'Internal server error, failed to get device list'
    });
  }
});


// 创建分组
deviceRouter.post('/createGroup', authenticateJWT, async (req, res) => {
  const userId = (req as any).user.userId;
  const { gname } = req.body;

  try {
    const group = await groupManager.createGroup(userId, gname);
    res.json({
      code: 200,
      message: '分组创建成功',
      data: { gid: group.gid, gname: group.gname }
    });
  } catch (err: any) {
    const msg = err.message;
    const code = msg.includes('已存在') ? 400 : msg.includes('最多') ? 409 : 400;
    res.status(code).json({ code, message: msg });
  }
});


// 设置设备分组
deviceRouter.post('/setGroup', authenticateJWT, async (req, res) => {
  const userId = (req as any).user.userId;
  const { device_id, group_id } = req.body;

  try {
    const result = await groupManager.setGroup(userId, device_id, group_id ?? null);
    res.json({ code: 200, message: '分组设置成功', data: result });
  } catch (err: any) {
    res.status(400).json({ code: 400, message: err.message });
  }
});


// 删除分组
deviceRouter.post('/deleteGroup', authenticateJWT, async (req, res) => {
  const userId = (req as any).user.userId;
  const { gid } = req.body;

  try {
    const count = await groupManager.deleteGroup(userId, gid);
    res.json({
      code: 200,
      message: '分组删除成功',
      data: { affected_devices: count }
    });
  } catch (err: any) {
    res.status(404).json({ code: 404, message: err.message });
  }
});


// 获取分组列表
deviceRouter.get('/groups', authenticateJWT, async (req, res) => {
  const userId = (req as any).user.userId;

  try {
    const groups = await groupManager.getGroups(userId);
    res.json({ code: 200, data: groups });
  } catch (err: any) {
    res.status(500).json({ code: 500, message: err.message });
  }
});


/**
 * 全部状态获取，仅初始化时使用
 */
deviceRouter.get('/status', authenticateJWT, async (req, res) => {
  const userId = (req as any).user.userId;

  try {
    // 检查品牌账户token是否过期
    const branchAccountRepo = AppDataSource.getRepository(BranchAccount);
    const accounts = await branchAccountRepo.find({ where: { userId } });

    // 检查是否有过期的token
    const now = new Date();
    const hasExpiredToken = accounts.some(account => account.expiresAt < now);

    if (hasExpiredToken) {
      res.status(401).json({
        code: 401,
        message: '品牌账户token无效或过期，请重新授权'
      });
      return;
    }

    const devices = await dm.getDevicesWithStatus(userId);
    res.json({
      code: 200,
      data: { devices }
    });
  } catch (err: any) {
    res.status(500).json({
      code: 500,
      message: '服务器内部错误'
    });
    return;
  }
});


// 设备控制路由
deviceRouter.post('/control', authenticateJWT, async (req: Request, res: Response) => {
  const userId = (req as any).user.userId;
  const { did, control } = req.body;

  if (!did || !control || !control.operation) {
    res.status(400).json({ code: 400, message: '参数不完整' });
    return;
  }

  const deviceRepo = AppDataSource.getRepository(Device);
  const device = await deviceRepo.findOne({ where: { did, userId } });

  if (!device) {
    res.status(404).json({ code: 1001, message: '设备不存在或不属于用户' });
    return;
  }

  const { operation, value } = control;

  // 校验操作属性是否在设备类型属性表中存在
  const capRepo = AppDataSource.getRepository(DeviceControlCapability);
  const supported = await capRepo.findOne({ where: { type: device.type, operation } });

  if (!supported) {
    res.status(400).json({ code: 1002, message: '属性不支持该类型设备' });
    return;
  }

  // 检查属性值是否合法
  const result = validateControlValue(device.type, operation, value);
  if (!result.valid) {
    res.status(400).json({ code: result.errorCode, message: result.errorMessage });
    return;
  }

  // 获取第三方 access_token
  const branchRepo = AppDataSource.getRepository(BranchAccount);
  const tokenRecord = await branchRepo.findOne({
    where: { userId, brand: device.brand }
  });

  if (!tokenRecord || !tokenRecord.token) {
    res.status(401).json({ code: 401, message: '第三方Token不存在，请先绑定账号' });
    return;
  }

  try {
    const strategy = getStrategy(device.brand);
    if (!('controlDevice' in strategy)) {
      res.status(501).json({ code: 1004, message: '该品牌不支持控制' });
      return;
    }

    await strategy.controlDevice(device.did, operation, value, tokenRecord.token);
    res.status(200).json({ code: 200, message: 'success' });
    return;
  } catch (e: any) {
     res.status(500).json({ code: 500, message: '服务器内部错误，控制失败：' + e.message });
     return;
  }
});



export default deviceRouter;

